#include "feapplication_private.h"
#include "fecore_private.h"
#include "feactualdataservice_private.h"
#include "femainwindow_private.h"
#include "fewidgetfactory_private.h"

#include "qt_windows.h"
#include "fecoremain.h"

#include <QPushButton>
#include <QDir>
#include <QPluginLoader>
#include <QStringList>
#include <QStyle>

#include "fedom.h"
#include "fescreenreader.h"
#include "fescreenbuilder_private.h"

FeApplication::FeApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
	init();
}

FeApplication::~FeApplication()
{
	delete mainwnd;
}

FeApplication *FeApplication::instance()
{
	return qobject_cast<FeApplication *>(QApplication::instance());
}

FeWidgetFactory *FeApplication::systemWidgetFactory() const
{
	return syswf;
}

void FeApplication::init()
{
	setApplicationName("frontend");
    setOrganizationName("Astra H CarPC Project");
    setOrganizationDomain("ru.astrahcarpc");

	loadPlugins();

	ads = new FeActualDataServiceImpl(this);
	fecore = new FeCoreImpl(this);
	syswf = new FeSystemWidgetFactory(this);

	mainwnd = new FeMainWindow();

	initPlugins();

	ads->start();

#ifdef Q_OS_WINCE
	mainwnd->showFullScreen();
#else
	mainwnd->setFixedSize(400, 234);
	mainwnd->show();
#endif
	
	// DEBUG
	{
		QFile file(QDir(QCoreApplication::applicationDirPath())
				.absoluteFilePath("skins/default/skin.qss"));
			if(!file.open(QIODevice::ReadOnly))
			{
				qDebug("StyleSheet read error");
				Q_ASSERT(false);
			}
			QDir::setSearchPaths("skin",
				QStringList(QCoreApplication::applicationDirPath() + "/skins/default"));

			setStyleSheet(file.readAll());
			file.close();
	}
	// DEBUG
	{
		FeDOMDocument screen_doc;
		{
			QFile file(QDir(QCoreApplication::applicationDirPath())
				.absoluteFilePath("screens/main.xml"));
			if(file.open(QIODevice::ReadOnly))
			{
				FeScreenReader reader(&file);
				reader.setResourceBaseDir(
					QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("screens"));
				
				if(!reader.read(screen_doc))
				{
					qDebug("XML read error: %s",
						reader.errorString().toLocal8Bit().constData());
					Q_ASSERT(false);
				}
				file.close();
			}
			else
			{
				Q_ASSERT(false);
			}
		}

		QWidget *screen_w = 0;
		{
			FeScreenBuilder builder;
			builder.setDocument(screen_doc);
			builder.setWidgetFactory(systemWidgetFactory());
			builder.setActualDataService(ads);
			screen_w = builder.buildScreen("main", mainwnd);
		}

		screen_w->show();
	}
}

void FeApplication::loadPlugins()
{
	qDebug("Load plugins...");
	QDir dir = QCoreApplication::applicationDirPath();
	foreach(QString fileName, dir.entryList(QStringList() << "feplugin_*.dll", QDir::Files))
	{
		QPluginLoader loader(dir.absoluteFilePath(fileName));
		FePluginInterface *plugin = qobject_cast<FePluginInterface *>(loader.instance());
		if(plugin)
		{
			qDebug("Load plugin: %s name: %s version: %s",
				fileName.toLocal8Bit().data(),
				plugin->getPluginName().toLocal8Bit().data(),
				plugin->getPluginVersion().toLocal8Bit().data()
				);
			plugins.append(plugin);
		}
		else
		{
			qWarning("Load plugin failed: %s", fileName.toLocal8Bit().data());
		}
	}
}

void FeApplication::initPlugins()
{
	foreach(FePluginInterface *plugin, plugins)
	{
		plugin->init();
	}
}

int fe_main(int argc, char **argv, PFESTARTER_CALLBACK callback) {
	int exit_code = 0;
	{
		FeApplication *app = new FeApplication(argc, argv);

		// hide splash screen
		callback->lpfnHideSplash(callback->lpParam);

		// enter main loop
		exit_code = app->exec();
		
		delete app;
	}
	return exit_code;
}